home *** CD-ROM | disk | FTP | other *** search
/ Hacker's Arsenal - The Cutting Edge of Hacking / Hacker's Arsenal - The Cutting Edge of Hacking.iso / texts / cracking1.txt < prev    next >
Text File  |  2001-07-11  |  27KB  |  625 lines

  1.                           CRACKING 101 - 1990 edition
  2.  
  3.  
  4.                                   Lession #1
  5.  
  6.  
  7.                             ┌────────────────────┐
  8.                             │ CRACKING DOS Files │
  9.                             └────────────────────┘
  10.  
  11.                               By Buckaroo Banzai
  12.  
  13.  
  14.     Today I'm here to about is cracking a dos format (either .EXE or .COM)
  15. file. This, in my mind is releativly the simplest (in theory although pratice
  16. might say otherwise) type of crack to do.
  17.  
  18.     There are really 3 steps in cracking a dos file. Step 1, is finding where
  19. the protection routine is. How to go about it, well, there are several
  20. diffrent methods. Here are the steps that I often use.
  21.  
  22.     First, I will run the program under PC-WATCH (PW) trapping INT13 all
  23. functions and INT21 functions 3Dh and 3Fh. Why trap the functions. This will
  24. give (hopefully) a starting place to look for the protection. Once you have
  25. set the breakpoints, press [F4] to execute and you will drop to dos. When you
  26. do, PW should display several calls to INT13. What closly at the CS:IP of
  27. these calls. Record it for later because these are calls from dos. We will
  28. uses this data to recognize what is a call to the protection and what is not.
  29.  
  30.     Next, run the program to be cracked. As it executes, PC-WATCH will show
  31. what files are opened (including the file you just ran since DOS uses
  32. function 3Dh to open a file when it executes one) and what (and more
  33. improtantly WHERE) data is read to. Makes a list saying what data is read in
  34. from what file. Here is an example. Lets say you ran the program "XXX.COM".
  35. While running, "XXX.COM", you noticed that 2 other files "YYY.BIN" and
  36. "ZZZ.BIN" were also opened. So make a list like this:
  37.  
  38.     XXX.COM       YYY.BIN       ZZZ.BIN
  39.     ───────       ───────       ───────
  40.  
  41.     Now, lets say that after "XXX.COM" was opened, PW showed that there were
  42. 2 reads from "XXX.COM" (the way to tell where the data is being read from is
  43. by checking the BX register on calls to 3Fh and the AX registers after calls
  44. to 3Dh. Yes, you should select both INPUT REGISTERS and OUTPUT REGISTERS from
  45. the PW menu) 1 at aaaa:bbbb and 1 as cccc:dddd. Right after "YYY.BIN" was
  46. opened, PW showed data was read to eeee:ffff and then after "ZZZ.BIN" was
  47. opened, data was written to gggg:hhhh and iiii:jjjj. Now, our list looks like
  48. this:
  49.  
  50.     XXX.COM       YYY.BIN       ZZZ.BIN
  51.     ───────       ───────       ───────
  52.     aaaa:bbbb     eeee:ffff     gggg:hhhh
  53.     cccc:dddd                   iiii:jjjj
  54.  
  55.     What we have just created in a program load map. This map shows where to
  56. program to be cracked is loaded in memory. Next, scan though the calls to
  57. INT13. Look for either calls that return with errors, calls that have high
  58. values in the CH ( > 28) or CL ( > 9) registers, or calls not made by dos
  59. (those calls that have a CS:IP diffrent from the one we copied down before we
  60. executed the program). Now, look at the CS:IP of the call to INT13. Match the
  61. segment address against the program load map. If only 1 match occurs, then
  62. you now know what module the check is in so continue on to step #2. If more
  63. than 1 match occurs, check the offset (IP). Find the one that is closest to
  64. one of the write address's offset. Once you find a match, then go on to step
  65. #2. If no match occurs after both steps, it's time to track through the
  66. program.
  67.  
  68.     Tracking your way though the program is a real bitch. I do not like to do
  69. because it can just take to long. But here is an overview on how it is done.
  70.  
  71.     The object, is to keep narowing down calls until disk access if found.
  72. How to do this. Well, load the program under debug. Keep tracing through the
  73. program in till a "CALL" instruction is found. Jot down you current IP and
  74. PROCEED (using debug P command) over the instruction without tracing in to
  75. it. If you end up at the next instruction without access that disk, then you
  76. have not found the routine you are looking for so keep going. Search for the
  77. next "CALL" and then the next and then the next etc. At some point, when you
  78. proceed over a call, the disk will either check protection or load in a new
  79. module.
  80.  
  81.     How to tell the diffrence, well PW is still active and will tell you if
  82. it was a call to INT13 or INT21 or BOTH. If it was the call to INT13 or a
  83. call to BOTH then you have found a call to the protection routine (although
  84. the actual call may be 100 levels deeper, you are on the right track). Exit
  85. and restart but this time when you reach the call, trace into it. Now do the
  86. same process until you get to the call to the next level, then again for the
  87. next, etc. Finally you should find where it is.
  88.  
  89.     But hopefully, you won't have to do that. As I said, it is very time
  90. consumming. Hopefully, you will know which module to look in. If you do, here
  91. is how to find the call to the protection. First, try the simple search
  92. method. Load up the module using DEBUG and simply type:
  93.  
  94.     S CS:100 FFFF CD 13  (use CS:100 if .EXE)
  95.  
  96.     Debug will hopefully list 1 or more address. If not, try the same command
  97. only using CS:0000. If again you are not givin any address, you have some
  98. tricky debugging at hand (an I suggest rereading the exercise in self-
  99. modifying code).
  100.  
  101.     I will explain in detail how to find self-modifying code later but for
  102. now, lets assume we have found the protection routine. Next, is to figure out
  103. what the copy protection is trying to do. First, look to the printout from
  104. PW. Look through it until you find the calls the INT13 from the protection
  105. routine. Look at the AH register. If it is 00h then the protection routine is
  106. probally reading in data from the protected tracks. If not, then the
  107. protection is simply looking for some KEY (in other words a damaged track or
  108. sector) that DOS cannot duplicate.
  109.  
  110.     The second choice is much eaiser to defeat. 2 quick methods to defeating
  111. this type. First, you can fake the call and simply set the registers. Take
  112. the follow check to a protection routine:
  113.  
  114.     1:      mov AX,0201h      ; Read 1 sectors using int 13h
  115.     2:      mov CX,2909h      ; Track 29h sector 09h
  116.     3:      xor DX,DX         ; Drive 0, head 0
  117.     4:      int 13h           ; Read sector
  118.     5:      jnc Bad           ; If no error then it's a copy
  119.     6:      cmp AH,10h        ; Was it a CRC error
  120.     7:      jne Bad           ; No, then it's a copy
  121.     8:      mov AX,0h         ; clear error flag
  122.     9:      jmp Done          ; we are done
  123.     Bad:    mov AX,1          ; set error flag
  124.     Done:   ret               ; we are done
  125.  
  126.     What is the above code trying to do. Well, it's checking for a KEY on
  127. track 29h. That key is sector 09h. Normally sector 09h would not have an
  128. error. On a read to the original disk, after the int13 (line 4) is executed,
  129. the carry flag (CF) would be set. The jnc in line 5 would jump if CF is not
  130. set (indicating no error, which is bad since the original disk would have an
  131. error there). The next line checks AH to see if it is 10h. This is checking
  132. to see if the error was a Bad CRC on the read (the error that should be
  133. there). If it was not, then again it is not the protected disk. Only after
  134. both of thoses conditions are met, will the protection routine return a
  135. "GOOD" result.
  136.  
  137.     The key here is the value returned in AX an possibly CF. When the disk is
  138. the original, AX would return the value of 0000h and CF = 1 but when it was a
  139. copy, it would return 0001h and CF = 0 or 1. Since on a bad return, CF can be
  140. 0 or 1 then it is preaty safe to assume CF is not used to signal the return.
  141. So what must we do to beat the protection routine, well, simply return from
  142. this CHECK with AX = 0000h. Simple. Just change line 1 to "mov AX,0000h" and
  143. line 2 to "RET". This will just bypass the check.
  144.  
  145.     Now, this example is quite simple and would probally never be used in a
  146. REAL protection routine. I kept it simple to show the point, see the example
  147. on how to crack DRAWING ASSISTANT for a better example.
  148.  
  149.     The second and more perferd method is to simply bypass the call to the
  150. protection routine and kill of the section of code that test for the check
  151. position. Take the following example:
  152.  
  153.     10:     call 1                  ; call the first example
  154.     11:     cmp AX,0                ; Was it the original
  155.     12:     jz  Good2               ; Yes, then good
  156.     13:     ... BAD it was a copy   ; No, then bad
  157.     Good2:
  158.  
  159.     The above example, when used with the last example show a typical call to
  160. a protection routine. The perfered method to crack this protection would not
  161. be to simply fake the return, but to remove the call to the protection. How
  162. to do it, simple. Just jump over the check. Change line 10 to "jmp Good2".
  163. This will bypass the protection routine.
  164.  
  165.     Now, you might ask why would you want to take the extra step of finding
  166. the call to the protection routine rather than simply faking an int13 and
  167. returning with the proper registers set. 2 reasons. First, What if there
  168. wasn't enough room to setup the registers the way you needed them. Then you
  169. would have to take the extra step. Second, what if somewhere down the line,
  170. that routine is used for something else (like the int13 is modified into an
  171. int10 in a game). Since you have changed the bytes at that location, the
  172. modifying routine would create code that wasn't exepcted. But as always, if
  173. you can fake the return, and the program works, leave it. After all, not to
  174. many people go around look at other peoples cracks (do they???).
  175.  
  176.     Now, what to do, if the program actually reads in important data from the
  177. disk. Well, there are 2 ways to go about this (possibly more). First, you
  178. could patch the program so that when it calls it's protection routine, it
  179. jumps to your user routine that opens a file and reads in the data to the
  180. right place. This method is preaty simple to add to a .COM file but a much
  181. harder to patch on to the back of a .EXE. I won't really go in to this method
  182. much more than to say use your brains. It's not a difficult concept.
  183.  
  184.     The other method, is to create a LOADER or a TSR. I suggest creating an
  185. Interrupt Service Routine (ISR) that handles loading in the data. For
  186. example, let say you wrote a routine to read in the needed data for a file.
  187. It is not to difficult to convert that routine into an ISR. (For notes on ISR
  188. and TSRs, try reading The Waite Group's "MS-DOS PAPERS". It has one of the
  189. best sections on the subject).
  190.  
  191.                        Consider this following example:
  192.  
  193.     A:            call 1           ; test protection
  194.     B:            jnc Good         ; was it successfull
  195.     C:            ... BAD load     ; no then it's a copy
  196.                   ... EXIT TO DOS  ; so exit to dos
  197.     Good:         ... Good load    ; yes then it original
  198.                   call 7C00:0000   ; then jump of protection
  199.                                    ; data
  200.  
  201.     1:            mov ax,0209      ; Read 9 sectors starting from
  202.     2:            mov cx,290a      ; Track 29h Sector 0Ah (10)
  203.     3:            xor dx,dx        ; for drive A: head 0
  204.     4:            mov bx,7c00      ; read to 7c00:0
  205.     5:            mov es,bx        ;
  206.     6:            mov bx,0         ;
  207.     7:            int 13h          ;
  208.     8:            ret
  209.  
  210.  
  211.     What the above example dos. Lines 1-8 try to read in sectors 0Ah -12h for
  212. track 29h on drive A:. This is the protection check routine. Lines A -Good
  213. attempt to check the protection, and then if the check is good (CF = 0) then
  214. a call to the loaded in code (the data loaded in by the protection check) is
  215. made.
  216.  
  217.     What we want to do, is somehow when INT 13h is called, load in the needed
  218. data for disk. Well, here is my suggestion. First, I would change line 7 from
  219. "int 13h" to "int BBh". Next, I would create a small .COM loader that would
  220. execute the main program as a child process (read the DOS TECH REF on the
  221. EXEC function). But before I did that, I would write an ISR (interrupt
  222. service routine) for INT BBh. Here is the general outline for the ISR
  223.  
  224.     ■ Use dos to open the file containing the needed data
  225.     ■ Read in the data to ES:BX (where int 13h would put it)
  226.     ■ Close the file ■ set AX to 0000 and clear CF
  227.     ■ iret
  228.  
  229.     The loader would go like this :
  230.  
  231.     ■ Get current int BBh address (DOS func. 35h)
  232.     ■ Set int BBh address to ours (DOS func. 25h)
  233.     ■ use DOS to EXECUTE (Dos func. 4Bh) the program to be cracked
  234.     ■ Restore the address of BBh
  235.  
  236.     Well, that about all I have to say about cracking a dos file. I hope this
  237. section has been usefull to you. Next I will show by example the techinques
  238. in this section while cracking I.B.M. Drawing Assistance (1.00).
  239.  
  240.     One last thing. After you have cracked the program, try running it from a
  241. hard drive with PW set to trap calls to INT 21h function 1Bh (get fat byte).
  242. If the program make a call to here, get the address and find that section of
  243. code. What the program is trying to do is check to see if you are running
  244. from a hard drive (most programs have diffrent protection routines for hard
  245. drives). When you find it, simply replace the "INT 21h" with a "MOV
  246. DS:[BX],FDh". This will fake the program in to thinking you are working on a
  247. floppy disk.
  248.  
  249.     Ok, for our example we will be removing the code from IBM's Drawing
  250. assistant. Now now, I know it's not the best program out there, but shit,
  251. It's hard to find shit with on disk copy protection anymore. So here we go...
  252.  
  253.     I needed 3 programs in cracking the assist. series. Locksmith by Alph
  254. Logic, Periscope debugger, and DEBUG (supplied with DOS). By using these
  255. three programs together, I was able to figure out and remove the copy
  256. protection in under 30 minutes.
  257.  
  258.     Drawing Assistant (DA) is IBM's answer to colorpaint for the Jr. It is a
  259. simple drawing program (a more advanced version is included in StoryBoard
  260. Deluxe) but easy to learn and use. So far, I have only seen version 1.00 of
  261. this program.
  262.  
  263.     DA made calls to the copy protection routine in 3 diffrent modules. The
  264. files "SETDRAW.EXE", "DRAWASST.EXE" and "DRAWASST.TWO" all contained calls to
  265. the copy protection. Also, "DRAWASST.TWO" and "DRAWASST.EXE" are for all
  266. intensive puporses then same file.
  267.  
  268.     I first started off by loading DRAWASST.EXE with debug and searched for
  269. any int 13's by executing the debug command
  270.  
  271.     s CS:0 FFFF CD 13         Search CS:0 - CS:FFFF for CD 13 (int 13)
  272.  
  273.     I located 2 diffrent calls to int 13h, so I then listed them. Here is
  274. what I found...
  275.  
  276.     { First, some initialization routines }
  277.  
  278.     18FD:0343 1E            PUSH   DS
  279.     18FD:0344 B80000        MOV    AX,0000
  280.     18FD:0347 50            PUSH   AX
  281.     18FD:0348 B89724        MOV    AX,2497
  282.     18FD:034B 8ED8          MOV    DS,AX
  283.     18FD:034D BB1000        MOV    BX,0010
  284.     18FD:0350 2E            CS:
  285.     18FD:0351 8A07          MOV    AL,[BX]
  286.     18FD:0353 3C00          CMP    AL,00
  287.     18FD:0355 7418          JZ     036F
  288.  
  289.       { This set is called if DA has been installed on the hard drive }
  290.                  { When cracked, this will NEVER be called }
  291.  
  292.     18FD:0357 B419          MOV    AH,19
  293.     18FD:0359 CD21          INT    21
  294.     18FD:035B 8AD0          MOV    DL,AL
  295.     18FD:035D FEC2          INC    DL
  296.     18FD:035F B41C          MOV    AH,1C
  297.     18FD:0361 CD21          INT    21
  298.     18FD:0363 8A07          MOV    AL,[BX]
  299.     18FD:0365 BB9724        MOV    BX,2497
  300.     18FD:0368 8EDB          MOV    DS,BX
  301.     18FD:036A 3CF8          CMP    AL,F8
  302.     18FD:036C 7475          JZ     03E3
  303.     18FD:036E CB            RETF
  304.  
  305.            { This set is called if DA is running from the floppy }
  306.  
  307.     18FD:036F B419          MOV    AH,19
  308.     18FD:0371 CD21          INT    21
  309.     18FD:0373 FEC0          INC    AL
  310.     18FD:0375 B400          MOV    AH,00
  311.     18FD:0377 A320C6        MOV    [C620],AX
  312.     18FD:037A 8AD0          MOV    DL,AL
  313.     18FD:037C B41C          MOV    AH,1C
  314.     18FD:037E CD21          INT    21
  315.     18FD:0380 8A07          MOV    AL,[BX]
  316.     18FD:0382 BB9724        MOV    BX,2497
  317.     18FD:0385 8EDB          MOV    DS,BX
  318.     18FD:0387 3CF8          CMP    AL,F8
  319.     18FD:0389 7408          JZ     0393
  320.  
  321.                 { Here is the called to read in the key disk }
  322.  
  323.     18FD:038B E8A675        CALL   7934
  324.     18FD:038E 3D0100        CMP    AX,0001
  325.     18FD:0391 7450          JZ     03E3
  326.  
  327.     Let's take these code segments 1 at a time. The fist, is some simple
  328. initialization routines. Here is the code, only this time full comments are
  329. added.
  330.  
  331.                    { First, some initialization routines }
  332.  
  333.     ; Setup for return to DOS
  334.  
  335.     18FD:0343 1E            PUSH   DS
  336.     18FD:0344 B80000        MOV    AX,0000
  337.     18FD:0347 50            PUSH   AX
  338.  
  339.     ; Setup DS to point to the data segment
  340.  
  341.     18FD:0348 B89724        MOV    AX,2497
  342.     18FD:034B 8ED8          MOV    DS,AX
  343.  
  344.  
  345.     18FD:034D BB1000        MOV    BX,0010    ; CS:10 points to
  346.                                               ; installed flag
  347.     18FD:0350 2E            CS:
  348.     18FD:0351 8A07          MOV    AL,[BX]
  349.  
  350.     18FD:0353 3C00          CMP    AL,00      ; If not installed, jump to
  351.                                               ; diskette
  352.     18FD:0355 7418          JZ     036F       ; routines
  353.  
  354.     What we are want to do, is fool DA in to thinking that it is stilling
  355. loading from diskette. Nothing really needs to be changed in this segment,
  356. but, just to be safe, we will force the jump at 355. To change the current
  357. values, use DEBUG's [A]ssembler command.
  358.  
  359.     A CS:355
  360.     18FD:355 JMP 36F
  361.  
  362.     Now, we have forced the jump, we can move on to the third code segment
  363. skipping over the second since it will never be called again. The 3rd code
  364. segment checks to see if you are using a hard drive. It does so by first
  365. getting the logical drive letter, then reading in the FAT descriptor byte for
  366. that drive. Here is the commented code.
  367.  
  368.            { This set is called if DA is running from the floppy }
  369.  
  370.     ; First, get the current drive
  371.  
  372.     18FD:036F B419          MOV    AH,19     ; DOS function 19h -; Get
  373.                                              ; Current Drive
  374.     18FD:0371 CD21          INT    21
  375.  
  376.     18FD:0373 FEC0          INC    AL         ; Add 1 for BIOS
  377.     18FD:0375 B400          MOV    AH,00      ; Clear AH
  378.     18FD:0377 A320C6        MOV    [C620],AX  ; Store it at C620
  379.     18FD:037A 8AD0          MOV    DL,AL      ; Store it in DL
  380.     18FD:037C B41C          MOV    AH,1C      ; DOS function 1Ch
  381.                                               ; Get Fat desc.
  382.     18FD:037E CD21          INT    21         ; returns pointer
  383.                                               ; in DS:BX
  384.     18FD:0380 8A07          MOV    AL,[BX]    ; Get the actual
  385.                                               ; byte
  386.     18FD:0382 BB9724        MOV    BX,2497    ; Restore DS
  387.     18FD:0385 8EDB          MOV    DS,BX
  388.  
  389.     18FD:0387 3CF8          CMP    AL,F8      ; Check to see if
  390.                                               ; it is a H/D
  391.     18FD:0389 7408          JZ     0393       ; Yes, then jump abort
  392.  
  393.     { Fall in to the check for the key disk }
  394.  
  395.     As you can see, this section of code is quite straigth forward. It just
  396. checks to see if you are using a hard drive. What we want to do is to fake an
  397. DOS function 1Ch and return the value for a floppy. This is done by putting
  398. the value of FDh in AL then NOPing the rest. Again use the Debug's [A]
  399. command.
  400.  
  401.     A CS:37C
  402.  
  403.     18FD:037C MOV AL,FD
  404.     18FD:0380 NOP
  405.     18FD:0381 NOP
  406.     18FD:0382 NOP
  407.     18FD:0383 NOP
  408.  
  409.     Now, you might ask why I didn't simple force a jump over the code. The
  410.  
  411. answer is what if DA uses the value at C620 at a later time (which it doesn't
  412. but let's pretend). If I had forced the jump then the value might not have
  413. been initialized and the crack might not work. Now that we have simulated
  414. running from diskette, we must deal for the check for the key disk.
  415.  
  416.     This is where Periscope came in to play. Using periscope, I made the
  417. above corrections and ran the program up till CS:038B (the call to the
  418. check). Here is the code, including the actual check. I have indented the
  419. check to make it easier to read.
  420.  
  421.                 { Here is the called to read in the key disk }
  422.  
  423.     18FD:038B E8A675        CALL   7934      ; Check key on disk
  424.                                              ; (track 27h side 0)
  425.  
  426.     18FD:7934 A120C6        MOV   AX,[C620]  ; Get drive letter
  427.     18FD:7937 FEC8          DEC   AL
  428.     18FD:7939 A23BC6        MOV   [C63B],AL  ; Store it for later
  429.     18FD:793C 1E            PUSH  DS
  430.     18FD:793D 07            POP   ES         ; Setup pointers to what sectors
  431.                                              ; to try to read
  432.  
  433.     18FD:793E BB30C6        MOV   BX,C630
  434.     18FD:7941 891E39C6      MOV   [C639],BX
  435.     18FD:7945 C6063CC603    MOV   BYTE PTR [C63C],03
  436.     18FD:794A C6063DC601    MOV   BYTE PTR [C63D],01
  437.  
  438.     ; Reset the disk
  439.  
  440.     18FD:794F B400          MOV   AH,00
  441.     18FD:7951 CD13          INT   13
  442.  
  443.     ; Get address of sector to read an put it in CL
  444.  
  445.     18FD:7953 8B1E39C6      MOV   BX,[C639]
  446.     18FD:7957 8A0F          MOV   CL,[BX]
  447.  
  448.  
  449.     ; Setup the rest of the read information
  450.  
  451.     18FD:7959 BBAE3D        MOV   BX,3DAE
  452.     18FD:795C 81C3D007      ADD   BX,07D0
  453.     18FD:7960 B001          MOV   AL,01
  454.     18FD:7962 B527          MOV   CH,27
  455.     18FD:7964 8A163BC6      MOV   DL,[C63B]
  456.     18FD:7968 B600          MOV   DH,00
  457.     18FD:796A B402          MOV   AH,02
  458.     18FD:796C CD13          INT   13
  459.  
  460.     ; Test for an error and jump if none is present (ie: the  copy protection
  461.       has been removed)
  462.  
  463.     18FD:796E 80FC00        CMP   AH,00
  464.     18FD:7971 740C          JZ    797F
  465.  
  466.     ; test the bad read (protection is missing) 3 times
  467.  
  468.     18FD:7973 FE0E3CC6      DEC   BYTE PTR [C63C]
  469.     18FD:7977 75D6          JNZ   794F
  470.     18FD:7979 B80000        MOV   AX,0000
  471.     18FD:797C EB13          JMP   7991
  472.  
  473.     ; Get next sector to check.  If finished, set the flag and ; return.
  474.  
  475.     18FD:797F FF0639C6      INC   WORD PTR [C639]
  476.     18FD:7983 FE063DC6      INC   BYTE PTR [C63D]
  477.     18FD:7987 803E3DC603    CMP   BYTE PTR [C63D],03
  478.     18FD:798C 75C1          JNZ   794F
  479.     18FD:798E B80100        MOV   AX,0001
  480.     18FD:7991 C3            RET
  481.  
  482.     ; Check to see if the OK flag was set (ax = 0001h means check was good)
  483.  
  484.     18FD:038E 3D0100        CMP    AX,0001
  485.     18FD:0391 7450          JZ     03E3
  486.  
  487.     The key check used in DA is quite simple. It simple tries to read in the
  488. illegaly numbered sectors on Track 27h side 0h. If they are missing, it
  489. assumes that it is running a pirated copy. What we must do, is to fool the
  490. scheme in to thinking a good read happened. I choses to fake the read using
  491. the easiest method. Since the protection scheme only check to see if AX
  492. returns the value > 0000h, I simply modified the routine at 1BFD:7934 to set
  493. AX to 0000h and then return. Here is the new code (enter using debug's A
  494. command)...
  495.  
  496.     A 1BFD:7934
  497.       1BFD:7934 MOV AX,0000
  498.       1BFD:7936 RET
  499.  
  500.     Now, this file is unprotected and if you type "G" at debug's command
  501. prompt, the program will execute, sort-of. See DRAWASST.EXE calls
  502. DRAWASST.TWO which also has the protection scheme. So both must be changed.
  503. To make to changes perement in DRAWASST.EXE, rename the file to DRAWASST.DEB
  504. and edit it. To find the address of the start of the protection code, use
  505. debug's search command...
  506.  
  507.     S CS:0 FFFF B4 19 CD 21 8A D0
  508.  
  509.     Now, just uses the modified address to change the program (the code will
  510. still be the same, just all calls and jumps will be to diffrent addresses).
  511. Use the same process to stip DRAWASST.TWO (it uses the exact same code).
  512. When you have both of those files unprotected, you can move on to
  513. unprotecting the setup program "SETDRAW.EXE"
  514.  
  515.     DRAWASST.EXE AND .TWO are not the only programs that make calls to the
  516. protection routine. SETDRAW.EXE also makes the above calls. Although the
  517. check here is much easier to bypass. Here is the asm listing of SETDRAW with
  518. all of the calls to the protection. This time, I will not go in to quite as
  519. much detail as I did for the other two version.
  520.  
  521.     I will tell you this. When SETDRAW checks the key disk, first it checks
  522. to see if the protection exists and then to see if the track hasn't been
  523. modified. It again uses AX to determine what happeded. I used Periscope to
  524. trace through the original version to find out what the correct values are.
  525. Here is the asm code...
  526.  
  527.     ; Initialization - checks the current mode and saves it.
  528.  
  529.     18FD:0000 1E            PUSH     DS
  530.     18FD:0001 B80000        MOV      AX,0000
  531.     18FD:0004 50            PUSH     AX
  532.     18FD:0005 B8321A        MOV      AX,1A32
  533.     18FD:0008 8ED8          MOV      DS,AX
  534.     18FD:000A B40F          MOV      AH,0F
  535.     18FD:000C CD10          INT      10
  536.     18FD:000E 3C02          CMP      AL,02
  537.     18FD:0010 740D          JZ       001F
  538.     18FD:0012 3C03          CMP      AL,03
  539.     18FD:0014 7409          JZ       001F
  540.     18FD:0016 A28900        MOV      [0089],AL
  541.     18FD:0019 B002          MOV      AL,02
  542.     18FD:001B B400          MOV      AH,00
  543.     18FD:001D CD10          INT      10
  544.  
  545.     ; Gets the current drive
  546.  
  547.     18FD:001F B400          MOV      AH,00
  548.     18FD:0021 B419          MOV      AH,19
  549.     18FD:0023 CD21          INT      21
  550.     18FD:0025 A28700        MOV      [0087],AL
  551.     18FD:0028 8AD0          MOV      DL,AL
  552.     18FD:002A FEC2          INC      DL
  553.  
  554.     ; Checks the FAT descriptor
  555.  
  556.     18FD:002C B41C          MOV      AH,1C
  557.     18FD:002E CD21          INT      21
  558.     18FD:0030 8A07          MOV      AL,[BX]
  559.     18FD:0032 BB321A        MOV      BX,1A32
  560.     18FD:0035 8EDB          MOV      DS,BX
  561.     18FD:0037 C606880000    MOV      BYTE PTR [0088],00
  562.     18FD:003C 3CF8          CMP      AL,F8
  563.     18FD:003E 742A          JZ       006A
  564.  
  565.     ; Read in protection scheme
  566.  
  567.     18FD:0040 8A168700      MOV      DL,[0087]
  568.     18FD:0044 E87E0A        CALL     0AC5
  569.     18FD:0047 C606880000    MOV      BYTE PTR [0088],00
  570.     18FD:004C 3D0000        CMP      AX,0000
  571.     18FD:004F 7419          JZ       006A
  572.  
  573.     ; Read in the dummy scheme
  574.  
  575.     18FD:0051 C606880001    MOV      BYTE PTR [0088],01
  576.     18FD:0056 8A168700      MOV      DL,[0087]
  577.     18FD:005A B84500        MOV      AX,0045
  578.     18FD:005D E8BD0A        CALL     0B1D
  579.     18FD:0060 3D0000        CMP      AX,0000
  580.     18FD:0063 7405          JZ       006A
  581.  
  582.     ; Start of actual routine.
  583.  
  584.     18FD:0065 C606880000    MOV      BYTE PTR [0088],00
  585.  
  586.     There is isn't much to say about the above code. To bypass it, we will
  587. change the hard drive check (int 21 function 1c). Do the same thing we did
  588. for DRAWASST.EXE
  589.  
  590.     A 18FD:2C
  591.       18FD:002C mov AL,FD
  592.       18FD:002E nop
  593.       18FD:002F nop
  594.       18FD:0030 nop
  595.       18FD:0031 nop
  596.  
  597.     Now, just jump over the check to the key disk.
  598.  
  599.     A 18FD:40
  600.  
  601.       18FD:0040 jmp 0065
  602.  
  603.     And thats it. Now SETDRAW is unprotected. Drawing Assistant may be used,
  604. copied or backed up at your pleasure.
  605.  
  606.     As you can see, this was a good example although the fact that if you
  607. only made the changes in DRAWASST.EXE and not in DRAWASST.TWO then the
  608. program would copy DRAWASST.TWO to DRAWASST.EXE to restore the protection was
  609. a bit strange.
  610.  
  611.     Well, I hope you are proud. But be warned, next we take on DOC checks, so
  612. get a good nights sleep. Till then, play lots of SMASH T.V.
  613.  
  614.     -Buckaroo
  615.       -Banzai
  616.  
  617.  
  618.  
  619.  
  620.  
  621.  
  622.  
  623.  
  624.  
  625. ... texts ...